all repos — caroster @ 33c19b84e5d8bc61df598d3b3a2fa6a02e6dee62

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid].tsx (view raw)

  1import {useState, useReducer, useEffect} from 'react';
  2import {useTranslation} from 'react-i18next';
  3import {initializeApollo} from '../../lib/apolloClient';
  4import useToastStore from '../../stores/useToastStore';
  5import useEventStore from '../../stores/useEventStore';
  6import Layout from '../../layouts/Default';
  7import AddToMyEventDialog from '../../containers/AddToMyEventDialog';
  8import TravelColumns from '../../containers/TravelColumns';
  9import NewTravelDialog from '../../containers/NewTravelDialog';
 10import WelcomeDialog from '../../containers/WelcomeDialog';
 11import EventBar from '../../containers/EventBar';
 12import Loading from '../../containers/Loading';
 13import Fab from '../../containers/Fab';
 14import OnBoardingTour from '../../containers/OnBoardingTour';
 15import {
 16  useUpdateEventMutation,
 17  Event as EventType,
 18  useEventByUuidQuery,
 19  EventByUuidDocument,
 20  EditEventInput,
 21} from '../../generated/graphql';
 22import ErrorPage from '../_error';
 23
 24const POLL_INTERVAL = 10000;
 25
 26interface Props {
 27  event: EventType;
 28  eventUUID: string;
 29}
 30
 31const EventPage = props => {
 32  const {t} = useTranslation();
 33  const {event} = props;
 34  if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />;
 35  return <Event {...props} />;
 36};
 37
 38const Event = (props: Props) => {
 39  const {eventUUID} = props;
 40  const {t} = useTranslation();
 41  const addToast = useToastStore(s => s.addToast);
 42  const setEvent = useEventStore(s => s.setEvent);
 43  const eventUpdate = useEventStore(s => s.event);
 44  const setIsEditing = useEventStore(s => s.setIsEditing);
 45  const [updateEvent] = useUpdateEventMutation();
 46  const [isAddToMyEvent, setIsAddToMyEvent] = useState(false);
 47  const [openNewTravel, toggleNewTravel] = useReducer(i => !i, false);
 48  const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({
 49    pollInterval: POLL_INTERVAL,
 50    variables: {uuid: eventUUID},
 51  });
 52
 53  useEffect(() => {
 54    if (event) setEvent(event as EventType);
 55  }, [event]);
 56
 57  const onSave = async e => {
 58    try {
 59      const {uuid, ...data} = eventUpdate;
 60      const {id, __typename, travels, users, waitingList, ...input} = data;
 61      await updateEvent({
 62        variables: {uuid, eventUpdate: input as EditEventInput},
 63        refetchQueries: ['eventByUUID'],
 64      });
 65      setIsEditing(false);
 66    } catch (error) {
 67      console.error(error);
 68      addToast(t('event.errors.cant_update'));
 69    }
 70  };
 71
 72  const onShare = async () => {
 73    if (!event) return null;
 74    // If navigator share capability
 75    if (!!navigator.share)
 76      return await navigator.share({
 77        title: `Caroster ${event.name}`,
 78        url: `${window.location.href}`,
 79      });
 80    // Else copy URL in clipboard
 81    else if (!!navigator.clipboard) {
 82      await navigator.clipboard.writeText(window.location.href);
 83      addToast(t('event.actions.copied'));
 84      return true;
 85    }
 86  };
 87
 88  if (!event) return <Loading />;
 89
 90  return (
 91    <Layout
 92      pageTitle={t('event.title', {title: event.name})}
 93      menuTitle={t('event.title', {title: event.name})}
 94      displayMenu={false}
 95    >
 96      <EventBar
 97        event={event}
 98        onAdd={setIsAddToMyEvent}
 99        onSave={onSave}
100        onShare={onShare}
101      />
102      <TravelColumns toggleNewTravel={toggleNewTravel} />
103      <Fab
104        color="primary"
105        open={openNewTravel}
106        onClick={toggleNewTravel}
107        aria-label="add-travel"
108      />
109      <NewTravelDialog open={openNewTravel} toggle={toggleNewTravel} />
110      <AddToMyEventDialog
111        event={event}
112        open={isAddToMyEvent}
113        onClose={() => setIsAddToMyEvent(false)}
114      />
115      <WelcomeDialog />
116      <OnBoardingTour />
117    </Layout>
118  );
119};
120
121export async function getServerSideProps(ctx) {
122  const {uuid} = ctx.query;
123  const apolloClient = initializeApollo();
124  const {data = {}} = await apolloClient.query({
125    query: EventByUuidDocument,
126    variables: {uuid},
127  });
128  const {eventByUUID: event} = data;
129  const {host = ''} = ctx.req.headers;
130
131  return {
132    props: {
133      event,
134      eventUUID: uuid,
135      metas: {
136        title: event?.name || '',
137        url: `https://${host}${ctx.resolvedUrl}`,
138      },
139    },
140  };
141}
142
143export default EventPage;